/*****************************************************************************
 *   Copyright 2005 Tim A Wang
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 ****************************************************************************/
package com.jb.web.application;

import com.jb.web.application.configuration.Config;

import java.io.PrintWriter;

import com.jb.faces.FactoryFinder;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * This is the entry point to a jb application. All the requests come to
 * this servlet  and will be dispatched to respective component based on the
 * request information. Response is prepared by writing to out stream.
 */
public class JBServlet extends HttpServlet {
    private static String APPLICATION_FACTORY = "com.jb.web.application.ApplicationFactoryImpl";
    private static String FACES_CONTEXT_FACTORY = "com.jb.web.context.WebContextFactory";
    private static String LIFECYCLE_FACTORY = "com.jb.web.lifecycle.LifecycleFactoryImpl";
    private static String RENDER_KIT_FACTORY = "com.jb.web.renderer.RenderKitFactoryImpl";

    static final long serialVersionUID = 123123L;
    static final Log log = LogFactory.getLog(JBServlet.class);
    private ApplicationImpl webApps;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, java.io.IOException {
        handleRequest(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, java.io.IOException {
        handleRequest(request, response);
    }

    public static String fatalError(String msg, Throwable e) {
        return HtmlConstants.getError(msg+"\n"+e.getMessage());
    }

    /**
     * Initialize application. Application is a singleton
     *
     * @param config
     *
     * @throws ServletException
     */
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        _init(config);
    }

    //internal application initialization
    private void _init(ServletConfig config) throws ServletException {
        FactoryFinder.releaseFactories();
        FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, APPLICATION_FACTORY);
        FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY, FACES_CONTEXT_FACTORY);
        FactoryFinder.setFactory(FactoryFinder.LIFECYCLE_FACTORY, LIFECYCLE_FACTORY);
        FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY, RENDER_KIT_FACTORY);

        ApplicationFactoryImpl applicationFactory = null;

        try {
            applicationFactory = (ApplicationFactoryImpl)FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
            applicationFactory.createApplication(config);
        } catch (Exception e) {
            throw new ServletException("Failed to get application factory ", e);
        }

        try {
            webApps = (ApplicationImpl) applicationFactory.getApplication();

            String webTop = config.getServletContext().getRealPath("/");
            webApps.getConfiguration().load(webTop);
        } catch (Exception e) {
            throw new ServletException("Failed to get application ", e);
        }
    }

    private void handleRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, java.io.IOException {
        //we only support UTF-8
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
   
        if(log.isDebugEnabled()) {
            log.debug(request);
        }
        //
        long pageStart = System.currentTimeMillis();
        try {
            if ("dialog".equals(request.getParameter("pageMode"))) {//dialog mode
                webApps.openDialog(request, response);
            } else if ("inspector".equals(request.getParameter("pageMode"))) {//inspector
                webApps.openInspector(request, response);
            } else if ("service".equals(request.getParameter("pageMode"))) {//external service
                webApps.processService(request, response);
            } else {//default process
                PrintWriter out = response.getWriter();
                webApps.process(request, response);
                pageStart = System.currentTimeMillis() - pageStart;
                out.flush();
            }                                                                                                                                                    
        } catch (PageSecurityException ae) {
            if (Config.getInstance().getDefaultPage() != null) {
                response.sendRedirect(Config.getInstance().getDefaultPage());
            } else {
                response.sendRedirect(Config.getInstance().getErrorPage());
            }
        } catch (Throwable e) {
            response.sendRedirect(Config.getInstance().getErrorPage());

            if (log.isErrorEnabled()) {
                log.error(this, e);
            }
        } finally {
            if(log.isDebugEnabled())
            {
                log.debug("Served " +request.getRequestURL()+  " in " + (new Double(pageStart).doubleValue() / 1000.) + " seconds");
            }
        }
    }
}
